package cn.hamster3.hamsterworld.data;

import cn.hamster3.api.HamsterAPI;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldBorder;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.UUID;

public class WorldData {
    private UUID owner;
    private UUID uuid;
    private String name;
    private long seed;
    private int borderSize;
    private boolean isPublic;
    private boolean isRealTime;
    private HashSet<UUID> allowedPlayer;

    public WorldData(UUID owner, UUID uuid, String name, long seed) {
        this.owner = owner;
        this.uuid = uuid;
        this.name = name;
        this.seed = seed;
        this.borderSize = 5000;
        this.isPublic = false;
        this.isRealTime = false;
        allowedPlayer = new HashSet<>();
    }

    public WorldData(ConfigurationSection config) {
        this.owner = UUID.fromString(config.getString("owner"));
        this.uuid = UUID.fromString(config.getString("uuid"));
        this.name = config.getString("name");
        this.seed = config.getLong("seed");
        this.borderSize = config.getInt("borderSize", 5000);
        this.isPublic = config.getBoolean("isPublic", false);
        this.isRealTime = config.getBoolean("isRealTime", false);
        this.allowedPlayer = new HashSet<>(HamsterAPI.deserialize(config.getStringList("allowedPlayer")));
    }

    public void save(File dataFolder) {
        try {
            YamlConfiguration config = new YamlConfiguration();
            config.set("owner", owner.toString());
            config.set("uuid", uuid.toString());
            config.set("name", name);
            config.set("seed", seed);
            config.set("borderSize", borderSize);
            config.set("isPublic", isPublic);
            config.set("isRealTime", isRealTime);
            config.set("allowedPlayer", HamsterAPI.serialize(new ArrayList<>(allowedPlayer)));
            config.save(new File(dataFolder, name + ".yml"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public UUID getOwner() {
        return owner;
    }

    public UUID getUuid() {
        return uuid;
    }

    public String getName() {
        return name;
    }

    public long getSeed() {
        return seed;
    }

    public World getWorld() {
        return Bukkit.getWorld(uuid);
    }

    public int getBorderSize() {
        return borderSize;
    }

    public void setBorderSize(int borderSize) {
        this.borderSize = borderSize;
        World world = getWorld();
        if (world == null) {
            return;
        }
        WorldBorder border = world.getWorldBorder();
        border.setDamageAmount(0.1);
        border.setDamageBuffer(10);
        border.setCenter(world.getSpawnLocation());
        border.setSize(borderSize);
    }

    public boolean isPublic() {
        return isPublic;
    }

    public void setPublic(boolean aPublic) {
        isPublic = aPublic;
    }

    public boolean isRealTime() {
        return isRealTime;
    }

    public void setRealTime(boolean realTime) {
        isRealTime = realTime;
    }

    public ArrayList<UUID> getAllowedPlayer() {
        return new ArrayList<>(allowedPlayer);
    }

    public void allowPlayer(UUID uuid) {
        allowedPlayer.add(uuid);
    }

    public void disallowPlayer(UUID uuid) {
        allowedPlayer.remove(uuid);
    }

    public boolean isAllowed(Player player) {
        return isPublic || owner.equals(player.getUniqueId()) || allowedPlayer.contains(player.getUniqueId()) || player.hasPermission("hw.admin");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        WorldData worldData = (WorldData) o;

        if (seed != worldData.seed) return false;
        return name.equals(worldData.name);
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}
